package com.yss.reportworld.service.impl;

import java.lang.reflect.Field;
import java.util.*;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yss.common.core.exception.BusinessException;
import com.yss.common.core.utils.StringUtils;
import com.yss.reportworld.domain.DatabaseDispose;
import com.yss.reportworld.enums.ReportWorldEnum;
import com.yss.reportworld.mapper.DatabaseDisposeMapper;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yss.reportworld.service.IDataCustomerService;
import com.yss.reportworld.mapper.DataCustomerMapper;
import com.yss.reportworld.domain.DataCustomer;

/**
 * 数据对应客户信息Service业务层处理
 *
 * @author yss
 * @date 2023-03-24
 */
@Slf4j
@Service
public class DataCustomerServiceImpl extends ServiceImpl<DataCustomerMapper, DataCustomer> implements IDataCustomerService {
    @Autowired
    private DatabaseDisposeMapper databaseDisposeMapper;

    /**
     * 查询所有的客户对应关系信息
     *
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, List<String>> getDataCustomerMap() {
        // 所属客户 code和数据，对应一个list
        QueryWrapper<DataCustomer> wrapper = new QueryWrapper<>();
        List<DataCustomer> customerList = this.list(wrapper);
        if (StringUtils.isEmpty(customerList)) {
            return null;
        }
        Map<String, List<String>> mapDataCustomer = new HashMap<>();
        for (DataCustomer customer : customerList) {
            if (null == customer || StringUtils.isEmpty(customer.getDataId()) || StringUtils.isEmpty(customer.getDataCode())) {
                continue;
            }
            String key = customer.getDataCode() + "\t" + customer.getDataId();
            if (mapDataCustomer.containsKey(key)) {
                List<String> list = mapDataCustomer.get(key);
                list.add(customer.getCustomerId());
                mapDataCustomer.put(key, list);
            } else {
                List<String> list = new ArrayList<>();
                list.add(customer.getCustomerId());
                mapDataCustomer.put(key, list);
            }
        }
        return mapDataCustomer;
    }


    /**
     * 导出数据客户个性化的处理
     * 每个数据的业务主键有相同数据的，如果选择了客户个性化，取客户个性化的那条，没有就取公用的那条
     */
    public List handleBusinessPrimaryCustomer(List list, String customerId, Class clazz) {
        TableName tableName = (TableName) clazz.getAnnotation(TableName.class);
        try {
            if (StringUtils.isEmpty(list)) {
                return list;
            }
            QueryWrapper<DataCustomer> dataCustomerQueryWrapper = new QueryWrapper<>();
            if (StringUtils.isNull(tableName)) {
                throw new BusinessException(clazz + "没有获取到注解TableName的值！");
            }
            Field[] fields = clazz.getDeclaredFields();
            List<String> rwIdS = new ArrayList<>();
            for (Object obj : list) { // 获取数据里的平台主键信息
                // 循环每个数据的业务主键信息
                StringJoiner joiner = new StringJoiner("/t");
                String rwdbId = "";
                rwdbId = getRwdbId(null, fields, obj, joiner, rwdbId);
                rwIdS.add(rwdbId);
            }
            if (StringUtils.isEmpty(rwIdS)) {
                return list;
            }
            List<DataCustomer> customerList = null;
            if (StringUtils.isEmpty(customerId)) { // 没有选择客户的时候，业务主键重复的数据，取公用，不取客户个性化的
                dataCustomerQueryWrapper.eq("DATA_CODE", tableName.value().toUpperCase());
                dataCustomerQueryWrapper.in("DATA_ID", rwIdS);
                customerList = this.list(dataCustomerQueryWrapper);
                if (StringUtils.isEmpty(customerList)) {
                    return list;
                }
            } else {
                // 查询这些信息是否存在客户个性化数据
                dataCustomerQueryWrapper.eq("DATA_CODE", tableName.value().toUpperCase());
                dataCustomerQueryWrapper.in("DATA_ID", rwIdS);
                dataCustomerQueryWrapper.in("CUSTOMER_ID", customerId);
                customerList = this.list(dataCustomerQueryWrapper);
                if (StringUtils.isEmpty(customerList)) {
                    return list;
                }
            }
            Map<String, String> mapDataCustomer = new HashMap<>();
            for (DataCustomer customer : customerList) {  // 数据存在个性化的情况
                mapDataCustomer.put(customer.getDataId(), customer.getCustomerId());
            }
            if (StringUtils.isEmpty(mapDataCustomer)) {
                return list;
            }
            // 业务主键字段
            QueryWrapper<DatabaseDispose> wrapper = new QueryWrapper<>();
            wrapper.eq("TABLE_NAME", tableName.value().toUpperCase());
            wrapper.eq("IS_BUSINESS_PRIMARY", 1);
            List<DatabaseDispose> listBusinessPrimary = databaseDisposeMapper.selectList(wrapper);
            if (StringUtils.isEmpty(listBusinessPrimary)) {
                throw new BusinessException("【" + tableName.value().toUpperCase().
                        replace(ReportWorldEnum.RW_DB_SUFFIX.getCode(), "") + "】没有获取到业务主键信息！");
            }
            // 客户个性化数据的业务主键信息
            Map<String, Integer> map = new HashMap<>();
            for (Object obj : list) {
                // 循环每个数据的业务主键信息
                StringJoiner joiner = new StringJoiner("/t");
                String rwdbId = "";
                rwdbId = getRwdbId(listBusinessPrimary, fields, obj, joiner, rwdbId);
                // 个性化数据的业务主键信息
                if (mapDataCustomer.containsKey(rwdbId)) {
                    map.put(joiner.toString(), 1);
                }
            }
            // 再次循环数据，如果业务主键相同的数据，只保留存在客户编码的
            List<Object> objectList = new ArrayList<>();
            for (Object obj : list) {
                StringJoiner joiner = new StringJoiner("/t");
                String rwdbId = "";
                rwdbId = getRwdbId(listBusinessPrimary, fields, obj, joiner, rwdbId);
                if (StringUtils.isEmpty(customerId)) {    // 客户编号为空的时候，排除个性化的数据
                    if (map.containsKey(joiner.toString()) && mapDataCustomer.containsKey(rwdbId)) {
                        continue;
                    }
                } else {   //业务主键已经存在 ，又不是个性化的数据不放进去
                    if (map.containsKey(joiner.toString()) && !mapDataCustomer.containsKey(rwdbId)) {
                        continue;
                    }
                }
                objectList.add(obj);
            }
            return objectList;
        } catch (Exception ex) {
            throw new BusinessException("【" + tableName.value().toUpperCase().
                    replace(ReportWorldEnum.RW_DB_SUFFIX.getCode(), "") + "】过滤业务主键信息失败！");
        }
    }

    private String getRwdbId(List<DatabaseDispose> listBusinessPrimary, Field[] fields, Object obj, StringJoiner joiner, String rwdbId) throws IllegalAccessException {
        for (Field field : fields) {
            if (StringUtils.isNull(field)) {
                continue;
            }
            field.setAccessible(true);
            TableField tableField = field.getAnnotation(TableField.class);
            if (StringUtils.isNull(tableField) || StringUtils.isEmpty(tableField.value()) || !tableField.exist()) {
                field.setAccessible(false);
                continue;
            }
            if ("RW_DB_ID".equals(tableField.value()) && null != field.get(obj)) {
                rwdbId = field.get(obj).toString();
            }
            if (StringUtils.isEmpty(listBusinessPrimary)) {
                continue;
            }
            // 业务主键的数据
            for (DatabaseDispose dispose : listBusinessPrimary) {
                if (tableField.value().equals(dispose.getProp())) {
                    if (null == field.get(obj)) {
                        joiner.add(null);
                        continue;
                    }
                    joiner.add(field.get(obj).toString());
                    continue;
                }
            }
            field.setAccessible(false);
        }
        return rwdbId;
    }
}
